﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using System.IO;
using System.IO.Ports;
using System.Threading;

namespace NatNetClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 

    public enum IConnectionType
    {
        Multicast = 0,
        Udp = 1
    }

    public partial class MainWindow : Window
    {
        private MyClientNatNet _natNetClient;
        private Dictionary<string, int> _ipList = new Dictionary<string, int>();

        public MainWindow()
        {
            InitializeComponent();

            _disconnetcBtn.IsEnabled = false;
            

            _IpSendToList.SelectedIndex = 0;
            _receivePacketNumber.Text = "0";
            _sendPacketNumber.Text = "0";
            LoadListFromXml();

            if ((_IpSendToList.Items.Count == 0) || (_SerialEnable.IsChecked == false && _UdpEnable.IsChecked == false))
                _connectBtn.IsEnabled = false;
            else
                _connectBtn.IsEnabled = true;

            FillDictionary();
        }

        void MainWindow_OnUpdate(object sender, EventArgs e)
        {
            if (this.Dispatcher.Thread == Thread.CurrentThread)
            {
                _receivePacketNumber.Text = _natNetClient.PacketReceived.ToString();
                _sendPacketNumber.Text = _natNetClient.PacketSent.ToString();
            }
            else
            {
                _receivePacketNumber.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new EventHandler(MainWindow_OnUpdate), sender, e);
            }
        }

        private void LoadListFromXml()
        {
            _IpSendToList.Items.Clear();
            XmlDocument document = new XmlDocument();
            try
            {
                document.Load("IpList.xml");
                foreach (XmlNode node in document.SelectNodes("/List/Address"))
                {
                    XmlNode ip = node.SelectSingleNode("Ip");
                    XmlNode port = node.SelectSingleNode("Port");

                    ListBoxItem item = new ListBoxItem();
                    item.Content = String.Format("{0}:{1}", ip.InnerText, port.InnerText);
                    _IpSendToList.Items.Add(item);
                }
            }
            catch (FileNotFoundException)
            {
            }
        }

        private void _connectBtn_Click(object sender, RoutedEventArgs e)
        {
            _sendPacketNumber.Text = "0";
            _receivePacketNumber.Text = "0";
            _disconnetcBtn.IsEnabled = true;
            _connectBtn.IsEnabled = false;
            MyClientNatNet.SENDMODE binaryMode = MyClientNatNet.SENDMODE.STRING;

            if (_isBinaryMode.IsChecked == true)
            {
                binaryMode = MyClientNatNet.SENDMODE.BINARY;
            }
            else if (_isStringMode.IsChecked == true)
            {
                binaryMode = MyClientNatNet.SENDMODE.STRING;
            }
            else if (_isMavlinkMode.IsChecked == true)
            {
                binaryMode = MyClientNatNet.SENDMODE.MAVLINK;
            }

            // nel costruttore 0 indica Multicast, 1 indica UDP (magari un enumerativo!)
            _natNetClient = new MyClientNatNet((int)IConnectionType.Udp, binaryMode);
            _natNetClient.OnUpdate += new EventHandler(MainWindow_OnUpdate);

            if (_UdpEnable.IsChecked == true && _SerialEnable.IsChecked == false) //HO SOLO UDP
            {
                FillDictionary();
                _natNetClient.Connect(_IpServer.Text, Convert.ToInt32(_DivFreq.Text), Convert.ToInt32(_IdObjTrack.Text), _ipList, null, null);
            }
            else if (_UdpEnable.IsChecked == false && _SerialEnable.IsChecked == true) //HO SOLO SERIALE
            {
                SerialPort serialPort = new SerialPort(_serialPort.Text, Convert.ToInt32(_baudeRateTxt.Text));
                SerialPort serialPort2 = null;
                if (cbUseSerial2.IsChecked.Value)
                {
                    serialPort2 = new SerialPort(_serialPort2.Text, Convert.ToInt32(_baudeRateTxt.Text));
                }
                _natNetClient.Connect(_IpServer.Text, Convert.ToInt32(_DivFreq.Text), Convert.ToInt32(_IdObjTrack.Text), null, serialPort, serialPort2);
            }
            else if (_UdpEnable.IsChecked == true && _SerialEnable.IsChecked == true) // HO ENTRAMBI LE COMUNICAZIONI
            {
                FillDictionary();
                SerialPort serialPort = new SerialPort(_serialPort.Text, Convert.ToInt32(_baudeRateTxt.Text));
                SerialPort serialPort2 = null;
                if (cbUseSerial2.IsChecked.Value)
                {
                    serialPort2 = new SerialPort(_serialPort2.Text, Convert.ToInt32(_baudeRateTxt.Text));
                }
                _natNetClient.Connect(_IpServer.Text, Convert.ToInt32(_DivFreq.Text), Convert.ToInt32(_IdObjTrack.Text), _ipList, serialPort, serialPort2);
            }


            _debugTxt.Text = _natNetClient.ServerDescription();
            if (_debugTxt.Text.Equals("Error Connecting."))
            {
                _disconnetcBtn.IsEnabled = false;
                _connectBtn.IsEnabled = true;
            }
        }

        private void FillDictionary()
        {
            foreach (ListBoxItem item in _IpSendToList.Items)
            {
                string[] list = item.Content.ToString().Split(':');
                int port = 0;
                if (!_ipList.TryGetValue(list[0], out port))
                {
                    _ipList.Add(list[0], Int32.Parse(list[1]));
                }
                else
                {
                    //_IpSendToList.Items.Remove(item); //se è già presente lo tolgo dalla list box
                }
            }
        }

        private void _disconnetcBtn_Click(object sender, RoutedEventArgs e)
        {
            _disconnetcBtn.IsEnabled = false;
            _connectBtn.IsEnabled = true;
            _natNetClient.Disconnect();
            _debugTxt.Text = "Disconnect";
            //_sendPacketNumber.Text = "0";
            //_receivePacketNumber.Text = "0";
        }

        private void _eraseItemListBtn_Click(object sender, RoutedEventArgs e)
        {
            if (_IpSendToList.SelectedItem != null)
            {
                string remove = ((ListBoxItem)_IpSendToList.SelectedItem).Content.ToString().Split(':')[0];
                _ipList.Remove(remove);
                _IpSendToList.Items.Remove(_IpSendToList.SelectedItem);
            }
            if (_IpSendToList.Items.Count == 0)
                _connectBtn.IsEnabled = false;
        }

        private void _addToListBtn_Click(object sender, RoutedEventArgs e)
        {
            AddIpList addWin = new AddIpList(_IpSendToList);
            addWin.ShowDialog();
            _ipList = new Dictionary<string, int>();
            FillDictionary();

            if (_IpSendToList.Items.Count > 0)
                _connectBtn.IsEnabled = true;
        }

        private void _saveListBtn_Click(object sender, RoutedEventArgs e)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.ASCII;
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create("IpList.xml", settings);
            writer.WriteStartDocument();
            writer.WriteStartElement("List");

            foreach (string ipAddr in _ipList.Keys)
            {
                writer.WriteStartElement("Address");
                writer.WriteElementString("Ip", ipAddr);
                writer.WriteElementString("Port", _ipList[ipAddr].ToString());
                writer.WriteEndElement(); //chiudo il tag Address
            }

            writer.WriteEndElement(); // chiudo il tag List
            writer.WriteEndDocument(); //chiudo documento

            writer.Close();

            MessageBox.Show("Salvataggio avvenuto con successo");
        }

        private void _UdpEnable_Checked(object sender, RoutedEventArgs e)
        {
            _addToListBtn.IsEnabled = true;
            _eraseItemListBtn.IsEnabled = true;
            _saveListBtn.IsEnabled = true;
            _connectBtn.IsEnabled = true;
            _IpSendToList.IsEnabled = true;
        }

        private void _UdpEnable_Unchecked(object sender, RoutedEventArgs e)
        {
            _addToListBtn.IsEnabled = false;
            _eraseItemListBtn.IsEnabled = false;
            _saveListBtn.IsEnabled = false;
            _IpSendToList.IsEnabled = false;
            if (_SerialEnable.IsChecked == false)
                _connectBtn.IsEnabled = false;
        }

        private void _SerialEnable_Checked(object sender, RoutedEventArgs e)
        {
            _serialPort.IsEnabled = true;
            _serialPort2.IsEnabled = true;
            _baudeRateTxt.IsEnabled = true;
            _connectBtn.IsEnabled = true;
        }

        private void _SerialEnable_Unchecked(object sender, RoutedEventArgs e)
        {
            _serialPort.IsEnabled = false;
            _serialPort2.IsEnabled = false;
            _baudeRateTxt.IsEnabled = false;
            if (_UdpEnable.IsChecked == false)
                _connectBtn.IsEnabled = false;
        }

        private void _IpServer_TextChanged(object sender, TextChangedEventArgs e)
        {

        }

    }
}
